package com.demo.app.util;

import io.jsonwebtoken.*;
import lombok.Data;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.Map;

/**
 * <p>
 * Jwt 工具类
 * </p>
 *
 * @author zhangxt
 * @date 2023/11/1
 */
@Data
public class JwtUtil {

    /**
     * 描述
     */
    private String secretKey;

    /**
     * 描述
     */
    private Long expiration;

    /**
     * 描述
     */
    private String issuer;

    public JwtUtil(String secretKey) {
        this.secretKey = secretKey;
    }

    public JwtUtil(String secretKey, String expiration, String issuer) {
        this.secretKey = secretKey;
        this.expiration = Long.valueOf(expiration);
        this.issuer = issuer;
    }

    /**
     * <p>
     * 由字符串生成加密key
     * </p>
     *
     * @param sKey
     * @return {@link SecretKey}
     */
    private SecretKey generalKey(String sKey) {
        byte[] encodedKey = Base64.getMimeDecoder().decode(sKey);
        return new SecretKeySpec(encodedKey, 0, encodedKey.length, "HmacSHA256");
    }

    /**
     * <p>
     * 生成JWT
     * </p>
     *
     * @param claims
     * @return {@link String}
     */
    public String createJWT(Map<String, Object> claims) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SecretKey key = generalKey(secretKey);
        // 构建jwt
        JwtBuilder builder = Jwts.builder();
        // 自定义载体
        builder.setClaims(claims);
        // token唯一ID
        builder.setId(String.valueOf(nowMillis));
        // iat: jwt的签发时间
        builder.setIssuedAt(now);
        // issuer：jwt签发人
        builder.setIssuer(issuer);
        if (expiration > 0) {
            long expMillis = nowMillis + expiration;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp);
        }
        builder.signWith(key, signatureAlgorithm);
        return builder.compact();
    }

    /**
     * <p>
     * 解密
     * </p>
     *
     * @param jwt
     * @return {@link Jws<Claims>}
     */
    public Jws<Claims> parseJWT(String jwt) {
        SecretKey key = generalKey(secretKey);
        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(jwt);
    }

}
